// 重构
// 1、将head 和 length前面的（属性修饰符）private更改为protected，这样继承其的子类也可以访问这两个署属性
// 2、新增属性：总是指向链表的尾部（因为循环链表总是要使用到尾部节点,所以新增，这样就要在添加，删除等地方都将tail指向尾部节点）
// 3、新增判断是否最后节点

import ILinkedList from "./LinkedList"
import {Node} from "./LinkedNode"
//2.创建LinkedList的类
export default class LinkList<T> implements ILinkedList<T> {
    protected head: Node<T> | null = null
    protected length: number = 0

    // 新增属性：总是指向链表的尾部
    protected tail: Node<T> | null = null;
    
    size(){
        return this.length
    }

    peek():T | undefined{
        return this.head?.value
    }

    //封装私有方法
    //根据position获取当前的节点(不是节点的value,而是获取节点)
    protected getNode(position:number):Node<T> | null{
        let index = 0;
        let current = this.head;
        while(index++ < position && current){
            current = current.next
        }
        return current
    }

     // 判断是否是最后一个节点
     private isTail(node:Node<T>):boolean{
        return this.tail === node
     }

    //追加节点,只在最后的位置插入
    append(value:T){
        //1.根据value创建一个新节点
        const newNode = new Node(value)
        //2.判断this.head是否为null
        if(!this.head){
            this.head = newNode
           
        }else{
            // 此时的this.tail是倒数第二个了
            this.tail!.next = newNode
        }
        this.tail = newNode
        //3.size++
        this.length++
    }

    //遍历链表的方法
    traverse(){
        //用来存储遍历出的节点
        const values: T[] = []
        //拿到第一个节点
        let current = this.head
        //当节点不为空时,一直向数组中追加节点
        while(current){
            values.push(current.value)
            if(this.isTail(current)){ // 已经遍历最后一个节点
                current = null;
            }else {  // 不是最后一个节点
                current = current.next
            }
        }
        // 这行代码只针对双向链表有用，循环链表
        if(this.head && this.tail?.next === this.head){
            values.push(this.head.value)
        }
        //打印
        console.log(values.join('->'))
    }

    //插入方法
    insert(value: T,position: number):boolean{
        //插入位置越界的时候
        if(position < 0 || position > this.length) return false
        const newNode = new Node(value)
        //如果插入位置在第一个
        if(position === 0 ) {
            //将新节点的下一个节点指向之前的头部
            newNode.next = this.head
            //将头部指向新节点
            this.head = newNode
        }else{
            
            const previous = this.getNode(position - 1)
            //将新节点的next指向要插入位置的老节点
            newNode.next = previous!.next
            //将老节点的前一个节点的next指向新节点
            previous!.next = newNode

            if(position === this.length){
                this.tail = newNode
            }
        }
        this.length++
        return true
    }

    //移除方法
    removeAt(position:number):T | null{
        console.log(position)
        //1、越界的判断
        if(position < 0 || position >= this.length) return null
        let current = this.head
        //判断删除的是否是第一个节点
        if(position === 0){
            this.head = current?.next ?? null

            if(this.length === 1){
                this.tail = null;
            }
        }else{
            //找到要删除节点的前一个节点
            const previous = this.getNode(position - 1)

            // 需要重新给current赋值,这样返回的才是删除的节点
              current = previous!.next
            //找到需要的节点
            previous!.next = previous?.next?.next ?? null
            // return previous?.next?.value ?? null

          
            if(position === this.length - 1){
                this.tail = previous
            }
        }
        this.length--
    
        return current?.value ?? null
    }


    //获取方法(根据索引获取对应的位置)
    get(position:number):T | null{
        //越界问题
        if(position < 0 || position >= this.length) return null;
        
        //查找元素
        const current = this.getNode(position)
        return current?.value ?? null
    }
    //更新方法
    update(value:T,position:number):boolean{
        if(position<0 || position >=this.length) return false
        //获取对应的节点，直接访问即可
        const current = this.getNode(position)
        current!.value = value
        return true
    }
    indexOf(value:T):number{
        //从第一个节点开始,向后遍历
        let current = this.head;
        let index = 0;
        while(current){
            if(current.value === value){
                return index
            }
            if(this.isTail(current)){
                current = null
            }else {
                 current = current.next
            }
            index++
        }
        return -1
    }
    //删除方法,根据value删除节点
    remove(value:T):T | null{
        const index = this.indexOf(value);
        // console.log(index)
        // const a =this.removeAt(index)
        // console.log('a',a)
        return this.removeAt(index)
    }
    //判断单链表是否为空的方法
    isEmpty():boolean{
        console.log('---',this.size)
        return this.length === 0
    }
}

const linkedList = new LinkList<string>()


linkedList.append('aaa')
linkedList.append('bbb')
linkedList.append('ccc')
linkedList.append('ddd')
linkedList.insert('555',2)
linkedList.insert('666',0)
linkedList.insert('777',6)
// linkedList.remove('ddd')
// linkedList.traverse()
// linkedList.traverse()
// linkedList.remove('aaa')
// linkedList.remove('bbb')
linkedList.traverse()

console.log(linkedList.removeAt(1))

linkedList.traverse()
// linkedList.removeAt(1)

// linkedList.traverse()
export {}